package com.laomuji.android.mvvm.base.rv

import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import com.laomuji.android.mvvm.utils.ReflectionUtil


/**
 * 所有RecyclerView的Adapter的基类
 * @author laomuji666
 * @since 2024/2/21
 */
abstract class BaseAdapter<VB : ViewBinding, T, VH : BaseViewHolder<VB, T>>(val context: Context) : RecyclerView.Adapter<VH>() {
    val dataList:ArrayList<T> = ArrayList()

    init {
        //启用固定的ItemID,必须重写getItemId,防止RecyclerView刷新导致的闪烁
        setHasStableIds(true)
    }

    /**
     * 在构造方法中调用,防止子类重写
     * @param hasStableIds 是否开启固定ID
     */
    final override fun setHasStableIds(hasStableIds: Boolean) = super.setHasStableIds(hasStableIds)

    /**
     * 获取Item的ID
     * @param position Item的下标
     */
    override fun getItemId(position: Int): Long = dataList[position].hashCode().toLong()

    /**
     * 通过反射的方式创建ViewHolder
     * @param parent 父容器
     * @param viewType 视图类型,需要重写getItemViewType,暂不支持该参数
     */
    @Suppress("UNCHECKED_CAST")
    final override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
        val viewBindingCls = ReflectionUtil.getGenericsClass<VB>(javaClass, 0) as Class<VB>
        val method = viewBindingCls.getMethod(
            "inflate",
            LayoutInflater::class.java,
            ViewGroup::class.java,
            Boolean::class.java
        )
        val viewBinding = method.invoke(null, LayoutInflater.from(context),parent,false) as VB
        val vhClazz = ReflectionUtil.getGenericsClass<VH>(javaClass, 2) as Class<VH>
        val constructor = vhClazz.constructors[0]
        //处理非静态内部类的情况
        if(constructor.parameterTypes.size == 2){
            return constructor.newInstance(this, viewBinding) as VH
        }
        return vhClazz.constructors[0].newInstance(viewBinding) as VH
    }

    /**
     * @return Item的个数
     */
    override fun getItemCount(): Int = dataList.size

    /**
     * @param holder ViewHolder对象
     * @param position 对应的下标
     */
    override fun onBindViewHolder(holder: VH, position: Int) = holder.setData(dataList[position],position)

    /**
     * 抑制警告
     * setHasStableIds已经解决闪烁问题了
     */
    @SuppressLint("NotifyDataSetChanged")
    fun notifyDataUpdate() = notifyDataSetChanged()
}